require 'rextral.rb'

class Normalize < Transform
      class Splitter
            # This method is for the singletable dynamic horizontally split
            def self.method_missing(method_name)
                  method_array = method_name.to_s.split("_")
                  if method_array.include? "horizontally"
                          $table_name = method_array[1..(method_array.index("horizontally")-1)].join("_")  
                          $split_columnname = nil
                          $split_rowposition = method_array.last
                  end    
                  return Splitter.new
            end


            # This method is for passing the connection attribute.
            # This is not ot be used in isolation.  
            def under connection
                  if !$split_rowposition.nil?  
                        table_name = Splitter.generate_missing_table_name($table_name,connection)
                        connection.execute("create table #{table_name} as (select * from #{$table_name} limit #{$split_rowposition.to_i})")
                        puts "#{$table_name} was sucessfully splitted"
                  end  
            end
        

            # This checks while creating the new table if there is a table of the same name
            # If the table is found then the tablename is changed.
            def self.generate_missing_table_name(table_name,connection)
                  all_tables = connection.tables
                  table_name = table_name+"new"
                  for table in all_tables
                        if table.to_s == table_name
                              table_name = table_name+"new"
                        end  
                end
                return table_name  
            end
        
            # This is for splitting different tables under different databases.
            def self.split_tables(options={})    
                  split_obj = Splitter.new
                  options.each{|key,hash_value|
                        for value in key
                            key_arr = value.split("_")
                            $table_name = key_arr[0..(key_arr.index("at")-1)].join("_")
                            $split_rowposition = key_arr.last
                            split_obj.under hash_value   
                        end    
                  }    
            end
      end
  

      # This is the method missing. Here the dynamic transformer calls are captured and the string is parsed.
      # Based on the hash given transformations are carried out.
      def self.method_missing(method_name,child_tables)
            root_table = method_name.to_s.split("_")
            root_table_name = root_table[0..root_table.index("to")-1].join("_")
            primary_key_for_root = root_table[root_table.index("primary")+2..root_table.length-1].join("_")
            connection = child_tables[:connection]
            if handle_primary_key(primary_key_for_root,root_table_name,connection) != 0
                  child_tables.each{|key,value|
                      all_columns = connection.query("desc #{root_table_name}")
                      if child_tables[:column_selection].downcase == "relative"
                            Normalize.generate_column_name_hash(key.to_s,value,root_table_name,primary_key_for_root,connection,all_columns) if key.to_s != "connection" && key.to_s != "relative"
                      elsif child_tables[:column_selection].downcase == "absolute"	
                            normalize(key,value,connection,root_table_name,primary_key_for_root) if key.to_s != "connection" && key.to_s != "absolute"
                      elsif child_tables[:column_selection].downcase == "numeric"
                            Normalize.get_columns_from_number(key,value,root_table_name,primary_key_for_root,connection,all_columns)
                      elsif child_tables[:column_selection].downcase == "hybrid"
                            Normalize.hybrid_option_query_generator(key,value,root_table_name,primary_key_for_root,connection,all_columns)	
                      end	
                  }
            end	
      end
	
  
  
      # This method calls the normalize methods based on the format of giving columns.
      def self.hybrid_option_query_generator(key,value,root_table_name,primary_key_for_root,connection,all_columns)	
            if value.respond_to? :split
                  Normalize.generate_column_name_hash(key,value,root_table_name,primary_key_for_root,connection,all_columns)
            elsif value.respond_to? :join
                  if value[0].respond_to? :abs
                        Normalize.get_columns_from_number(key,value,root_table_name,primary_key_for_root,connection,all_columns)
                  elsif value[0].respond_to? :split
                        Normalize.normalize(key,value,connection,root_table_name,primary_key_for_root)	
                  end		
            end		
      end	

	

      # When the columns are mentioned as the numbers representing their positions from the root table.
      # this method will generate the column names for them and call the class level normalize method.
      def self.get_columns_from_number(tablename,number_arr,root_table,primary_key_for_root,connection,all_columns)
              if tablename.to_s != "column_selection" && tablename.to_s != "connection"
                    column_names = []
                    column_array = []
                    column_counter = 1
                    for column in all_columns
                          if number_arr.include?column_counter
                              column_names << column[0]
                          end
                          column_counter = column_counter + 1
                    end
                    Normalize.normalize(tablename,column_names,connection,root_table,primary_key_for_root)
              end	
      end	
	
  
  
      # If the columns are mentioned as the relative positions of the root tables 
      # then this method will build an array of those columnnames and will pass them to the normalize method.	
      def self.generate_column_name_hash(key,value,root_table,primary_key_for_root,connection,all_columns)
            if key != "column_selection" && key != "connection"
                  column_names = get_columns_from_positions(value,all_columns)
                  Normalize.normalize(key,column_names,connection,root_table,primary_key_for_root)
            end	
      end	
	
  
      # This method is actually building the normalization query
      def self.normalize(key,value,connection,root_table,primary_key_for_root)
              if key.to_s != "column_selection"
                      query_string = "CREATE TABLE "+key.to_s+" ("
                      for single_value in value
                              if single_value.respond_to?"join"
                                    single_value = single_value[0]
                              end	
                              if single_value == primary_key_for_root || single_value == first_letter_capital(primary_key_for_root) || single_value == primary_key_for_root.capitalize || single_value == primary_key_for_root.gsub(/\_/,"") 
                                    primary_key_already_added = true
                              end		
                              col_specs = get_the_col_spec_for_single_col(single_value.to_s,root_table,connection)
                              query_string << single_value+" "+col_specs
                              if value.size > 1
                                    if (single_value != value.last) || (single_value == value.last && !primary_key_already_added)
                                          query_string << ","
                                    end  
                              end	  
                      end
                      if !primary_key_already_added
                              possible_primary_key = get_possible_primary_key(primary_key_for_root,root_table,connection)
                              col_specs = get_the_col_spec_for_single_col(possible_primary_key,root_table,connection)
                              query_string << possible_primary_key+" "+col_specs
                      end	
                      query_string << ")"
                      puts query_string
              end	
      end	    

end	

